/**
 * @file lib_syscall.c
 * @author lcz (you@domain.com)
 * @brief
 * @version 0.1
 * @date 2022-11-03
 *
 * @copyright Copyright (c) 2022
 *
 */

#include "applib/lib_syscall.h"
#include "core/syscall.h"
#include <stdlib.h>
#include <string.h>
/**
 * @brief 特权级3运行的系统调用函数，睡眠的毫秒值
 *
 * @param ms 休眠的毫秒
 * @return * void
 */
void msleep(int ms)
{
    if (ms <= 0)
    {
        return;
    }
    // 通过调用门实现
    syscall_args_t args;
    args.id = SYS_sleep;
    args.arg0 = ms;
    sys_call(&args);
}

/**
 * @brief 获取进程进程号pid，这里简单处理为获取进程的地址（指针），这是唯一的，但是没有大小关系
 * 父子进程关系比较难确认
 *
 * @return * int
 */
int getpid(void)
{
    // 通过调用门实现
    syscall_args_t args;
    args.id = SYS_getpid;
    return sys_call(&args);
}
/**
 * @brief 临时使用的打印函数，只支持两个参数，一个字符串，一个整型值，内部实现是log_printf
 *
 * @param fmt 格式化字符串
 * @param arg 参数
 * @return * void
 */
void print_msg(const char *fmt, int arg)
{
    syscall_args_t args;
    args.id = SYS_printmsg;
    args.arg0 = (uint32_t)fmt;
    args.arg1 = arg;

    sys_call(&args);
}

/**
 * @brief 创建子进程
 *
 * @return * int 父进程返回子进程id，子进程返回0
 */
int fork(void)
{
    syscall_args_t args;
    args.id = SYS_fork;
    return sys_call(&args);
}

// name argv env
/**
 * @brief 执行磁盘文件
 *
 * @param name
 * @param argv
 * @param env
 * @return * int
 */
int execve(const char *name, char *const *argv, char *const *env)
{
    syscall_args_t args;
    args.id = SYS_execve;
    args.arg0 = (int)name;
    // (char **)new_argv =
    args.arg1 = (int)argv;
    args.arg2 = (int)env;
    return sys_call(&args);
}

/**
 * @brief 进程主动放弃cpu
 *
 * @return * int
 */
int yield(void)
{
    syscall_args_t args;
    args.id = SYS_yield;
    return sys_call(&args);
}
/**
 * @brief 进程退出
 */
void _exit(int status)
{
    syscall_args_t args;
    args.id = SYS_exit;
    args.arg0 = (int)status;
    sys_call(&args);
}
/**
 * @brief 进程等待，等待处理子进程结束并释放其资源
 * @param status 放回的状态值
 */
int wait(int *status)
{
    syscall_args_t args;
    args.id = SYS_wait;
    args.arg0 = (int)status;
    return sys_call(&args);
}

/**
 * @brief 打开文件
 *
 * @param name
 * @param flags
 * @param ...
 * @return * int
 */
int open(const char *name, int flags, ...)
{
    syscall_args_t args;
    args.id = SYS_open;
    args.arg0 = (int)name;
    args.arg1 = (int)flags;
    return sys_call(&args);
}
/**
 * @brief 读取文件
 *
 * @param file
 * @param ptr
 * @param len
 * @return * int
 */
int read(int file, char *ptr, int len)
{
    syscall_args_t args;
    args.id = SYS_read;
    args.arg0 = (int)file;
    args.arg1 = (int)ptr;
    args.arg2 = (int)len;
    return sys_call(&args);
}
/**
 * @brief 写入文件
 *
 * @param file
 * @param ptr
 * @param len
 * @return * int
 */
int write(int file, char *ptr, int len)
{
    syscall_args_t args;
    args.id = SYS_write;
    args.arg0 = (int)file;
    args.arg1 = (int)ptr;
    args.arg2 = (int)len;
    return sys_call(&args);
}
/**
 * @brief 关闭文件
 *
 * @param file
 * @return * int
 */
int close(int file)
{
    syscall_args_t args;
    args.id = SYS_close;
    args.arg0 = (int)file;
    return sys_call(&args);
}
/**
 * @brief 调整文件指针
 *
 * @param file
 * @param ptr
 * @param dir
 * @return * int
 */
int lseek(int file, int ptr, int dir)
{
    syscall_args_t args;
    args.id = SYS_lseek;
    args.arg0 = (int)file;
    args.arg1 = (int)ptr;
    args.arg2 = (int)dir;
    return sys_call(&args);
}

// #define SYS_isatty 55
// #define SYS_fstat 56
// #define SYS_sbrk 57
int isatty(int file)
{
    syscall_args_t args;
    args.id = SYS_isatty;
    args.arg0 = (int)file;
    return sys_call(&args);
}
int fstat(int file, struct stat *st)
{
    syscall_args_t args;
    args.id = SYS_fstat;
    args.arg0 = (int)file;
    args.arg1 = (int)st;
    return sys_call(&args);
}
void *sbrk(ptrdiff_t incr)
{
    syscall_args_t args;
    args.id = SYS_sbrk;
    args.arg0 = (int)incr;
    return (void *)sys_call(&args);
}

int dup(int file)
{
    syscall_args_t args;
    args.id = SYS_dup;
    args.arg0 = (int)file;
    return sys_call(&args);
}
